package com.mall.web.service;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import com.mall.pay.config.PayConfig;
import com.mall.pay.wxpay.config.WxpayConfig;
import com.mall.pay.wxpay.util.CommonUtil;
import com.mall.pay.wxpay.util.HttpClientUtil;
import com.mall.pay.wxpay.util.RequestHandler;
import com.mall.pay.wxpay.util.WxApi;
import net.sf.json.JSONObject;

/**
 * @author lisj
 * @time 2016年7月19日 下午1:58:07
 */
@Service
public class WxService {
	private Logger logger = LoggerFactory.getLogger(WxService.class);
	@Resource JdbcTemplate jdbcTemplate;

	/**
	 * 获取扫码支付的链接（模式二）
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getCodeurl(Map<String, Object> product) throws Exception {
		String platform_type =MapUtils.getString(product,"platform_type");
		String orderType =MapUtils.getString(product,"orderType");
		String payType=WxpayConfig.pcpay;
		Map<String, Object> configMap = PayConfig.getWxpayConfig(platform_type,payType);
		if (configMap != null) {
			String appid = MapUtils.getString(configMap,"appid");
			String mch_id =MapUtils.getString(configMap,"mch_id");
			String appsecret = MapUtils.getString(configMap,"appsecret");
			String partnerkey =MapUtils.getString(configMap,"partnerkey");
			Map<String, String> packageParams = new TreeMap<String, String>();
			// 调用接口提交的交易类型，取值如下：JSAPI，NATIVE，APP
			String trade_type = "NATIVE";
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			// 商品信息
			packageParams.put("body", MapUtils.getString(product,"body"));
			// 附加数据 原样返回
			JSONObject jsonAttach=new JSONObject();
			jsonAttach.put("platform_type", platform_type);
			jsonAttach.put("orderType",orderType);
			jsonAttach.put("payType",payType);
			jsonAttach.put("orderName", MapUtils.getString(product,"body"));
			packageParams.put("attach", jsonAttach.toString());
			// 订单号
			packageParams.put("out_trade_no",MapUtils.getString(product,"orderId"));
			// 总金额以分为单位，不带小数点
			String totalFee = WxApi.getMoney(MapUtils.getString(product,"total_fee"));
			// 金额
			packageParams.put("total_fee", totalFee);
			// APP和网页支付提交用户端ip,必须
			packageParams.put("spbill_create_ip",MapUtils.getString(product,"ip"));
			// 随机字符串，不长于32位。
			packageParams.put("nonce_str", WxApi.getNonceStr());
			// 接收微信支付异步通知回调地址
			packageParams.put("notify_url", WxpayConfig.notifyurl);
			// 交易类型
			packageParams.put("trade_type", trade_type);
			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid, appsecret, partnerkey);
			String sign = reqHandler.createSign(packageParams);
			// 微信返回的签名
			packageParams.put("sign", sign);
			String xml = CommonUtil.ArrayToXml(packageParams);
			String code_url = WxApi.getCodeUrl(WxpayConfig.createOrderURL, xml);
			logger.info("code_url:" + code_url);
			return code_url;
		} else {
			logger.info("获取支付配置信息失败！");
			return "";
		}

	}

	/**
	 * 获取请求预支付id报文
	 * 
	 * @return
	 */
	public String getPackage(Map<String, Object> product) {
		logger.info("H5支付传入参数："+product);
		// 平台类型
		String platform_type =MapUtils.getString(product,"platform_type");
		// 订单交易类型，用于不同的业务处理的判断
		String orderType =MapUtils.getString(product, "orderType");
		String payType=WxpayConfig.h5pay;
		Map<String, Object> configMap = PayConfig.getWxpayConfig(platform_type,payType);
		if (configMap != null) {
			String appid = MapUtils.getString(configMap,"appid");
			String mch_id =MapUtils.getString(configMap,"mch_id");
			String appsecret = MapUtils.getString(configMap,"appsecret");
			String partnerkey =MapUtils.getString(configMap,"partnerkey");
			String openId =MapUtils.getString(product,"openId");
			// 调用接口提交的交易类型，取值如下：JSAPI，NATIVE，APP
			String trade_type = "JSAPI";
			String noncestr = WxApi.getNonceStr();
			SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			// 随机字符串，不长于32位。
			packageParams.put("nonce_str", noncestr);
			// 商品信息
			packageParams.put("body", MapUtils.getString(product,"body"));
			// 附加信息，原样返回,由于微信回调地址不允许带参数，所以如果想传入自定义参数，可以通过该参数。
			JSONObject jsonAttach=new JSONObject();
			jsonAttach.put("platform_type", platform_type);
			jsonAttach.put("payType",payType);
			jsonAttach.put("orderName", MapUtils.getString(product,"body"));
			jsonAttach.put("orderType",orderType);
			packageParams.put("attach", jsonAttach.toString());
			// 订单号
			packageParams.put("out_trade_no", MapUtils.getString(product,"orderId"));
			// 这里写的金额为1 分到时修改
			String totalFee = WxApi.getMoney(MapUtils.getString(product,"total_fee"));
			// 金额
			packageParams.put("total_fee", totalFee);
			// APP和网页支付提交用户端ip,必须
			packageParams.put("spbill_create_ip",MapUtils.getString(product,"ip"));
			// 接收微信支付异步通知回调地址
			packageParams.put("notify_url", WxpayConfig.notifyurl);
			// 交易类型
			packageParams.put("trade_type", trade_type);
			// 用户的openid，必须
			packageParams.put("openid", openId);
			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid, appsecret, partnerkey);
			String sign = reqHandler.createSign(packageParams);
			// 签名
			packageParams.put("sign", sign);
			String xml = CommonUtil.ArrayToXml(packageParams);
			String prepay_id = WxApi.getPayNo(WxpayConfig.createOrderURL, xml);
			// 获取prepay_id后，拼接最后请求支付所需要的package
			SortedMap<String, String> finalpackage = new TreeMap<String, String>();
			String timestamp = CommonUtil.getTimeStamp();
			String packages = "prepay_id=" + prepay_id;
			finalpackage.put("appId", appid);
			finalpackage.put("timeStamp", timestamp);
			finalpackage.put("nonceStr", noncestr);
			finalpackage.put("package", packages);
			finalpackage.put("signType", "MD5");
			String finalsign = reqHandler.createSign(finalpackage);
			finalpackage.put("paySign", finalsign);
			String result = JSONObject.fromObject((finalpackage)).toString();
			logger.info("统一下单获取的package:" + result);
			return result;
		} else {
			logger.info("获取支付配置信息失败！");
			return "";
		}
	}

	/**
	 * 扫码支付的回调（模式二）
	 * 
	 * @return
	 */
	public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 读取参数
		InputStream inputStream;
		StringBuffer sb = new StringBuffer();
		inputStream = request.getInputStream();
		String s;
		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
		while ((s = in.readLine()) != null) {
			sb.append(s);
		}
		in.close();
		inputStream.close();

		// 解析xml成map
		Map<String, String> m = new HashMap<String, String>();
		m = CommonUtil.parseXml(sb.toString());
		// 过滤空 设置 TreeMap
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		Iterator it = m.keySet().iterator();
		while (it.hasNext()) {
			String parameter = (String) it.next();
			String parameterValue = m.get(parameter);
			String v = "";
			if (null != parameterValue) {
				v = parameterValue.trim();
			}
			packageParams.put(parameter, v);
		}
		// 处理业务开始-------
		String resXml = "";
		logger.info("回调返回参数======="+packageParams);
		if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
			////////// 执行自己的业务逻辑////////////////
			platformBusiness(packageParams);
			////////// 执行自己的业务逻辑////////////////
			logger.info("支付成功！");
			// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
			resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
					+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
		} else {
			logger.info("支付失败,错误信息：" + packageParams.get("err_code"));
			resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
					+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
		}
		// 处理业务完毕-------
		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
		out.write(resXml.getBytes());
		out.flush();
		out.close();
	}

	public String orderIsSuccess(Map<String, Object> queryParam) {
		Map<String, Object> map = orderQuery(queryParam);
		if (!map.isEmpty() && "SUCCESS".equals(map.get("trade_state").toString())) {
			return "SUCCESS";
		} else {
			return "FAIL";
		}
	}

	public static Map<String, Object> orderQuery(Map<String, Object> queryParam) {
		String platform_type =MapUtils.getString(queryParam,"platform_type");
		Map<String, Object> configMap = PayConfig.getWxpayConfig(platform_type, WxpayConfig.pcpay);
		Map<String, Object> orderInfo =new HashMap<String, Object>();
		if (configMap != null) {
			String appid =MapUtils.getString(configMap,"appid");
			String mch_id = MapUtils.getString(configMap,"mch_id");
			String appsecret = MapUtils.getString(configMap,"appsecret");
			String partnerkey = MapUtils.getString(configMap,"partnerkey");
			Map<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("nonce_str", WxApi.getNonceStr());
			packageParams.put("out_trade_no", MapUtils.getString(queryParam,"orderId"));
			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid,appsecret,partnerkey);
			String sign = reqHandler.createSign(packageParams);
			packageParams.put("sign", sign);
			String xml = CommonUtil.ArrayToXml(packageParams);
			orderInfo = WxApi.orderQuery(WxpayConfig.orderqueryURL, xml);
		}
		return orderInfo;
	}

	/**
	 * 平台业务处理
	 */
	public void platformBusiness(Map<Object, Object> packageParams){
		String attach =MapUtils.getString(packageParams,"attach");
		JSONObject attachJson=JSONObject.fromObject(attach);
		String platform_type=MapUtils.getString(attachJson, "platform_type");
		String payType=MapUtils.getString(attachJson, "payType");
		String orderName=MapUtils.getString(attachJson, "orderName");
		String orderType=MapUtils.getString(attachJson, "orderType");
		Map<String,Object> recordMap=new HashMap<String, Object>();
		recordMap.put("platform_type",platform_type);
		recordMap.put("orderType",orderType);
		recordMap.put("orderId",MapUtils.getString(packageParams, "out_trade_no"));
		recordMap.put("total_fee",WxApi.getMoneyBy2Point(MapUtils.getString(packageParams, "total_fee")));
		recordMap.put("order_name", orderName);
		recordMap.put("pay_type", payType);
		recordMap.put("buyer_id",MapUtils.getString(packageParams,"openid"));
		recordMap.put("create_date",MapUtils.getString(packageParams,"time_end"));
		recordMap.put("update_date",MapUtils.getString(packageParams,"time_end"));
		recordMap.put("trade_no",MapUtils.getString(packageParams,"transaction_id") );
		// 记录订单数据
		addOrderRecord(recordMap);
		// 平台回调
		Map<String, Object> configMap=PayConfig.getWxpayConfig(platform_type, payType);
		String platform_notifyUrl=MapUtils.getString(configMap, "notify_url");
		if(StringUtils.isNotBlank(platform_notifyUrl)){
			HttpClientUtil.postJson(platform_notifyUrl,JSONObject.fromObject(recordMap).toString());
		}
	}
	public void addOrderRecord(Map<String, Object> recordMap) {
		try {
			if (recordMap != null) {
				String platform_type = MapUtils.getString(recordMap, "platform_type");
				String payType = MapUtils.getString(recordMap, "pay_type");
				String orderId = MapUtils.getString(recordMap, "orderId");
				String total_fee = MapUtils.getString(recordMap, "total_fee");
				String order_name = MapUtils.getString(recordMap, "order_name");
				String buyer_id = MapUtils.getString(recordMap, "buyer_id");
				String create_date = MapUtils.getString(recordMap, "create_date");
				String update_date = MapUtils.getString(recordMap, "update_date");
				String trade_no = MapUtils.getString(recordMap, "trade_no");
				String sql = "insert into tb_pay_record (platform_type, pay_type, orderId, total_fee, order_name, buyer_id, create_date, update_date,trade_no) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?)";
				jdbcTemplate.update(sql,platform_type, payType, orderId, total_fee, order_name, buyer_id,
						create_date, update_date, trade_no);
				logger.info("新增订单信息======" + recordMap);
			}
		} catch (Exception e) {
			logger.info("新增订单失败======" + e.getMessage());
		}
	}

}
